package com.vaha.presentation.rest;

import com.alibaba.fastjson.JSONObject;
import com.cyber.application.controller.AuthingTokenController;
import com.cyber.domain.constant.HttpResultCode;
import com.cyber.domain.entity.DataResponse;
import com.cyber.domain.entity.IdRequest;
import com.cyber.domain.entity.PagingData;
import com.cyber.domain.entity.Response;
import com.vaha.application.service.ProductFollowService;
import com.vaha.application.service.ProductItemService;
import com.vaha.application.service.ProductService;
import com.vaha.domain.entity.Product;
import com.vaha.domain.entity.ProductFollow;
import com.vaha.domain.entity.ProductItem;
import com.vaha.domain.request.*;
import lombok.RequiredArgsConstructor;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RestController
@RequiredArgsConstructor
public class ProductRest extends AuthingTokenController {

    private final ProductService productService;

    private final ProductItemService productItemService;

    private final ProductFollowService productFollowService;

    @GetMapping("/user/product/search")
    public Response searchProduct(@Valid ProductRequest request) {
        DataResponse<PagingData<Product>> response = new DataResponse<>();
        Product product = request.toEvent(getTenantCode());
        PagingData<Product> productPage = productService.selectPage(product);
        if (!CollectionUtils.isEmpty(productPage.getData())) {

            ProductFollow productFollow = new ProductFollow();
            productFollow.setLimit(Integer.MAX_VALUE);
            JSONObject user = getUser();
            productFollow.setUserCode(user.getString("code"));
            List<ProductFollow> productFollows = productFollowService.selectByIndex(productFollow);

            if (!CollectionUtils.isEmpty(productFollows)) {
                Map<String, List<ProductFollow>> productFollowMap = productFollows.stream()
                        .filter(productfollow -> StringUtils.isEmpty(productfollow.getProductItemCode()))
                        .collect(Collectors.groupingBy(ProductFollow::getProductCode));

                for (Product datum : productPage.getData()) {
                    List<ProductFollow> productFollowData = productFollowMap.getOrDefault(datum.getCode(), null);
                    if (!CollectionUtils.isEmpty(productFollowData)) {
                        Set<Integer> productFollowStats = productFollowData.stream().map(ProductFollow::getType).collect(Collectors.toSet());
                        datum.setProductFollowStats(productFollowStats);
                    }
                }

            }

        }

        response.setData(productPage);
        return response;
    }

    @GetMapping("/user/product")
    public Response selectOneProduct(@Valid IdRequest idRequest) {
        DataResponse<Product> response = new DataResponse<>();

        Product product = new Product();
        product.setId(idRequest.getId());
        product.setTenantCode(getTenantCode());
        product = productService.selectOne(product);

        if (Objects.isNull(product)) {
            return response;
        }

        ProductFollow productFollow = new ProductFollow();
        productFollow.setLimit(Integer.MAX_VALUE);
        productFollow.setProductCode(product.getCode());
        productFollow.setProductType(product.getType());
        JSONObject user = getUser();
        productFollow.setUserCode(user.getString("code"));
        List<ProductFollow> productFollows = productFollowService.selectByIndex(productFollow);
        Set<Integer> productFollowStats = productFollows.stream()
                .filter(productfollow -> StringUtils.isEmpty(productfollow.getProductItemCode()))
                .map(ProductFollow::getType).collect(Collectors.toSet());
        product.setProductFollowStats(productFollowStats);

        ProductItem productItem = new ProductItem();
        productItem.setLimit(Integer.MAX_VALUE);
        productItem.setSortBy("order_num");
        productItem.setSortType("asc");
        productItem.setProductCode(product.getCode());

        List<ProductItem> productItems = productItemService.selectByIndex(productItem);

        if (!CollectionUtils.isEmpty(productItems)) {
            productFollow.setProductType(null);

            List<ProductFollow> productItemFollows = productFollowService.selectByIndex(productFollow);

            if (!CollectionUtils.isEmpty(productItemFollows)) {
                Map<String, List<ProductFollow>> productFollowMap = productItemFollows.stream().filter(productFollow1 ->
                        !StringUtils.isEmpty(productFollow1.getProductItemCode()))
                        .collect(Collectors.groupingBy(ProductFollow::getProductItemCode));

                for (ProductItem datum : productItems) {
                    List<ProductFollow> productFollowData = productFollowMap.getOrDefault(datum.getCode(), null);
                    if (!CollectionUtils.isEmpty(productFollowData)) {
                        Set<Integer> productItemFollowStats = productFollowData.stream().map(ProductFollow::getType).collect(Collectors.toSet());
                        datum.setProductFollowStats(productItemFollowStats);
                    }
                }

            }

        }

        product.setItems(productItems);

        response.setData(product);
        return response;
    }

    @GetMapping("/admin/product/search")
    public Response searchAdminProduct(@Valid ProductRequest request) {
        DataResponse<PagingData<Product>> response = new DataResponse<>();
        Product product = request.toEvent(getTenantCode());
        PagingData<Product> productPage = productService.selectPage(product);
        response.setData(productPage);
        return response;
    }


    @GetMapping("/admin/product")
    public Response selectOneAdminProduct(@Valid IdRequest idRequest) {
        DataResponse<Product> response = new DataResponse<>();

        Product product = new Product();
        product.setId(idRequest.getId());
        product.setTenantCode(getTenantCode());
        product = productService.selectOne(product);

        response.setData(product);
        return response;
    }

    @PostMapping("/admin/product")
    public Response saveProduct(@RequestBody @Valid CreateProductRequest request) {
        Product product = request.toEvent(getSessionId(), getTenantCode());

        int result = productService.save(product);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @PutMapping("/admin/product")
    public Response updateProduct(@RequestBody @Valid UpdateProductRequest request) {
        Product product = request.toEvent(getSessionId(), getTenantCode());
        int result = productService.updateById(product);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @DeleteMapping("/admin/product")
    public Response deleteProduct(@Valid IdRequest idRequest) {
        Product product = new Product();
        product.setId(idRequest.getId());

        product.setTenantCode(getTenantCode());
        product.setUpdator(getSessionId());
        product.setUpdateTime(new Date());

        int result = productService.deleteById(product);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }


    @GetMapping("/admin/productitem/search")
    public Response searchProductItem(@Valid ProductItemRequest request) {
        DataResponse<PagingData<ProductItem>> response = new DataResponse<>();
        ProductItem productitem = request.toEvent(getTenantCode());
        PagingData<ProductItem> productItemPage = productItemService.selectPage(productitem);
        response.setData(productItemPage);
        return response;
    }


    @GetMapping("/admin/productitem")
    public Response selectOneProductItem(@Valid IdRequest idRequest) {
        DataResponse<ProductItem> response = new DataResponse<>();

        ProductItem productItem = new ProductItem();
        productItem.setId(idRequest.getId());
        productItem.setTenantCode(getTenantCode());
        productItem = productItemService.selectOne(productItem);

        response.setData(productItem);
        return response;
    }

    @PostMapping("/admin/productitem")
    public Response saveProductItem(@RequestBody @Valid CreateProductItemRequest request) {
        ProductItem productitem = request.toEvent(getSessionId(), getTenantCode());

        int result = productItemService.save(productitem);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @PutMapping("/admin/productitem")
    public Response updateProductItem(@RequestBody @Valid UpdateProductItemRequest request) {
        ProductItem productitem = request.toEvent(getSessionId(), getTenantCode());
        int result = productItemService.updateById(productitem);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }

    @DeleteMapping("/admin/productitem")
    public Response deleteProductItem(@Valid IdRequest idRequest) {
        ProductItem productItem = new ProductItem();
        productItem.setId(idRequest.getId());

        productItem.setTenantCode(getTenantCode());
        productItem.setUpdator(getSessionId());
        productItem.setUpdateTime(new Date());

        int result = productItemService.deleteById(productItem);
        if (result < 1) {
            return Response.fail(HttpResultCode.SERVER_ERROR);
        }
        return Response.success();
    }
}
